#include <BlenderFilter.h>
#include <Picture.h>

#include <highgui.h>
#include <cv.h>
#include <iostream>

using namespace std;

bool BlenderFilter::init() {
    if (!background.isInitialized()) return false;
    background.getMatrix().copyTo(blended);
    return true;
}


BlenderFilter::BlenderFilter(const Picture& bg, const vector <cv::Mat> fg):
    background(bg),
    foreground(fg)
{
    initialized = init();
}

BlenderFilter::~BlenderFilter() {
    destroy();
}
void BlenderFilter::destroy() {
    // We don't handle memory allocations
}

bool BlenderFilter::refresh(cv::Mat& image) const {
    // Copy the current state
    blended.copyTo(image);
    return true;
}

int BlenderFilter::nextIter(void* moreData) {
    // blendPoint is the starting point (in the background) for the blending process
    cv::Point blendPoint;
    // Check if we got some data
    if(moreData){
        // We trust the programmer to send us only a Point* instance
        blendPoint = *(cv::Point*)moreData;
    }else{
        // If no data was given we take (0,0)
        blendPoint = cv::Point(0,0);
    }
    // Copy the background - We don't want to destory the original (for future interaction)
    cv::Mat bgCopy;
    background.getMatrix().copyTo(bgCopy);
    
    // Extract the object mask and image
    cv::Mat  objMask = foreground[0];    
    cv::Mat  objMat =  foreground[1];

    // Make sure we don't go out-of-bounds
    int width  = min(objMat.cols, bgCopy.cols - blendPoint.x);
    int height = min(objMat.rows, bgCopy.rows - blendPoint.y);
    // Limit the object to the calculated bounds
    cv::Mat  objRoi = cv::Mat(objMat, cv::Rect(0,0,width,height) );
    cv::Mat  maskRoi = cv::Mat(objMask, cv::Rect(0,0,width,height) );
    // limit the background to the calculated bounds
    cv::Mat bgRoi(bgCopy,cv::Rect(blendPoint.x,blendPoint.y,width,height));
    // Do a simple blend
    objRoi.copyTo(bgRoi, maskRoi);  
    blended = bgCopy;
    return 0;
}

boost::shared_ptr<Picture> BlenderFilter::exportPicture() {
    // We don't want to handle the delete alone, we love boost!
    return boost::shared_ptr<Picture>(new Picture(blended));
}

